/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Boolean State Query tests.
 *//*--------------------------------------------------------------------*/

#include "es31fBooleanStateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "tcuRenderTarget.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using namespace gls::StateQueryUtil;

static const char* getVerifierSuffix (QueryType type)
{
	switch (type)
	{
		case QUERY_ISENABLED:	return "isenabled";
		case QUERY_BOOLEAN:		return "getboolean";
		case QUERY_INTEGER:		return "getinteger";
		case QUERY_INTEGER64:	return "getinteger64";
		case QUERY_FLOAT:		return "getfloat";
		default:
			DE_ASSERT(DE_FALSE);
			return DE_NULL;
	}
}

class IsEnabledStateTestCase : public TestCase, private glu::CallLogWrapper
{
public:
	IsEnabledStateTestCase (Context& context, QueryType verifier, const char* name, const char* description, glw::GLenum targetName, bool initial, glu::ApiType minimumContextVersion)
		: TestCase				(context, name, description)
		, glu::CallLogWrapper	(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
		, m_targetName			(targetName)
		, m_initial				(initial)
		, m_verifier			(verifier)
		, m_minimumVersion		(minimumContextVersion)
	{
	}

	IterateResult iterate (void)
	{
		if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)))
			TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(m_context.getRenderContext().getType(), m_minimumVersion), "This test requires a higher context version.");

		tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
		enableLogging(true);

		// check inital value
		verifyStateBoolean(result, *this, m_targetName, m_initial, m_verifier);

		// check toggle

		GLU_CHECK_CALL(glEnable(m_targetName));

		verifyStateBoolean(result, *this, m_targetName, true, m_verifier);

		GLU_CHECK_CALL(glDisable(m_targetName));

		verifyStateBoolean(result, *this, m_targetName, false, m_verifier);

		result.setTestContextResult(m_testCtx);
		return STOP;
	}

private:
	const glw::GLenum		m_targetName;
	const bool				m_initial;
	const QueryType			m_verifier;
	const glu::ApiType		m_minimumVersion;
};

} // anonymous

BooleanStateQueryTests::BooleanStateQueryTests (Context& context)
	: TestCaseGroup(context, "boolean", "Boolean State Query tests")
{
}

BooleanStateQueryTests::~BooleanStateQueryTests (void)
{
}

void BooleanStateQueryTests::init (void)
{
	const bool isDebugContext = (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;

	static const QueryType isEnabledVerifiers[] =
	{
		QUERY_ISENABLED,
		QUERY_BOOLEAN,
		QUERY_INTEGER,
		QUERY_INTEGER64,
		QUERY_FLOAT
	};

#define FOR_EACH_VERIFIER(VERIFIERS, X)															\
	do {																						\
		for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); ++verifierNdx)	\
		{																						\
			const char* verifierSuffix = getVerifierSuffix((VERIFIERS)[verifierNdx]);			\
			const QueryType verifier = (VERIFIERS)[verifierNdx];								\
			this->addChild(X);																	\
		}																						\
	} while (0)

	struct StateBoolean
	{
		const char*		name;
		const char*		description;
		glw::GLenum		targetName;
		bool			value;
		glu::ApiType	minimumContext;
	};

	{
		const StateBoolean isEnableds[] =
		{
			{ "sample_mask",				"SAMPLE_MASK",				GL_SAMPLE_MASK,					false,			glu::ApiType::es(3, 1)},
			{ "sample_shading",				"SAMPLE_SHADING",			GL_SAMPLE_SHADING,				false,			glu::ApiType::es(3, 2)},
			{ "debug_output",				"DEBUG_OUTPUT",				GL_DEBUG_OUTPUT,				isDebugContext,	glu::ApiType::es(3, 2)},
			{ "debug_output_synchronous",	"DEBUG_OUTPUT_SYNCHRONOUS",	GL_DEBUG_OUTPUT_SYNCHRONOUS,	false,			glu::ApiType::es(3, 2)},
		};

		for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(isEnableds); testNdx++)
		{
			FOR_EACH_VERIFIER(isEnabledVerifiers, new IsEnabledStateTestCase(m_context, verifier, (std::string(isEnableds[testNdx].name) + "_" + verifierSuffix).c_str(), isEnableds[testNdx].description, isEnableds[testNdx].targetName, isEnableds[testNdx].value, isEnableds[testNdx].minimumContext));
		}
	}

#undef FOR_EACH_VERIFIER
}

} // Functional
} // gles31
} // deqp
